package web.dao;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collection;

import org.apache.log4j.Logger;

import common.LogCategory;

import dbu.jdbc.JdbcDriver;

public class Session {

	static {
		try {
			Class.forName("dbu.jdbc.JdbcDriver");
			Connection connection = DriverManager.getConnection(JdbcDriver.URL);
			statement = connection.createStatement();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
	protected static final Logger log = LogCategory.getCategory(Session.class);
	private static Statement statement;

	Session() {
	}

	public void beginTransaction() {
	}

	public void rollbackTransaction() {
	}

	public Query createQuery(String tableName, Class<?> persistentClass) {
		return new Query(tableName, persistentClass);
	}

	public int executeUpdate(String sql) {
		try {
			return statement.executeUpdate(sql);
		} catch (SQLException e) {
			log.error(e.getMessage(), e);
		}
		return 0;
	}

	public <T> Collection<T> executeQuery(Class<T> persistentClass, String sql) {
		Collection<T> result = new ArrayList<T>();
		try {
			ResultSet resultSet = statement.executeQuery(sql);

			if (!resultSet.first()) {
				log.warn("Not found!");
			} else {
				log.debug("Found several.");
				do {
					T bean = getBean(persistentClass, resultSet);
					result.add(bean);
				} while (resultSet.next());
			}
		} catch (SQLException e) {
			log.error(e.getMessage(), e);
		}
		return result;
	}

	public static <T> T getBean(Class<T> persistentClass, ResultSet resultSet) {
		T bean = null;
		try {
			ResultSetMetaData meta = resultSet.getMetaData();
			Constructor<T> constructor = persistentClass.getConstructor(new Class[0]);
			bean = constructor.newInstance(new Object[0]);
			for (int index = 0; index < meta.getColumnCount(); index++) {
				String paramName = meta.getColumnName(index);
				String setterName = "set" + paramName.substring(0, 1).toUpperCase() + paramName.substring(1);
				Class<?>[] params = new Class[] {String.class};
				Method method = persistentClass.getMethod(setterName, params);
				if (method != null) {
					method.invoke(bean, resultSet.getString(index));
				}
			}
		} catch (SQLException e) {
			log.error(e.getMessage(), e);
		} catch (IllegalArgumentException e) {
			log.error(e.getMessage(), e);
		} catch (InstantiationException e) {
			log.error(e.getMessage(), e);
		} catch (IllegalAccessException e) {
			log.error(e.getMessage(), e);
		} catch (InvocationTargetException e) {
			log.error(e.getMessage(), e);
		} catch (SecurityException e) {
			log.error(e.getMessage(), e);
		} catch (NoSuchMethodException e) {
			log.error(e.getMessage(), e);
		}
		return bean;
	}
}
